#ifndef __LAMPE__VECTOR3D_H__
#define __LAMPE__VECTOR3D_H__

#include <lampe/base_type_vendor.h>
#include <lampe/stream/Serializable.h>

namespace lampe{

template <typename T>
class vector3d:public stream::Serializable{
private:
	T*_x;
	T*_y;
	T*_z;
	bool freeOnExit;
public:

	vector3d(){
		_x=new T();
		_y=new T();
		_z=new T();
		set(0,0,0);
		freeOnExit=true;
	}

	vector3d(T x,T y,T z){
		_x=new T();
		_y=new T();
		_z=new T();
		set(x,y,z);
		freeOnExit=true;
	}

	vector3d(T*mem){
		_x=&mem[0];
		_y=&mem[1];
		_z=&mem[2];
		freeOnExit=false;
	}

	vector3d(T*mX,T*mY,T*mZ){
		_x=mX;
		_y=mY;
		_z=mZ;
		freeOnExit=false;
	}

	~vector3d(){
		if (freeOnExit){
			delete _x;
			delete _y;
			delete _z;
		}
	}

	//T X;
	//T Y;
	//T Z;

	T&X(){
		return *_x;
	}

	T&Y(){
		return *_y;
	}

	T&Z(){
		return *_z;
	}

    f32 lengthSQ(){
		return X()*X()+Y()*Y()+Z()*Z();
    }

    f32 length(){
        return sqrt(lengthSQ());
    }
	vector3d<T> normalize(){
		if (X()==0 && Y()==0 && Z()==0)
            return *this;
        f64 l=1/length();

		X()=(T)(X()*l);
		Y()=(T)(Y()*l);
		Z()=(T)(Z()*l);
        return*this;
    }
	virtual void serialization(stream::IWriter*stream){
		stream->write(&X(),sizeof(T));
		stream->write(&Y(),sizeof(T));
		stream->write(&Z(),sizeof(T));
	}

	virtual void deserialization(stream::IReader*stream){
		stream->read(&X(),sizeof(T));
		stream->read(&Y(),sizeof(T));
		stream->read(&Z(),sizeof(T));
	}

	void set(T x,T y,T z){
		*_x=x;
		*_y=y;
		*_z=z;
	}
};

typedef vector3d<u32> Vector3u;
typedef vector3d<s32> Vector3i;
typedef vector3d<f32> Vector3f;

}//namespace lampe


#endif
